<template>
  <div class="graphic-three">
    <div class="data-tree-title f-mb">
      <a-space>
        <p>分组管理:</p>
        <p class="title-icon" title="新增分组" @click="addNewPlotTree(true, null)">
          <mars-icon icon="plus-cross" width="14"></mars-icon>
        </p>
        <p class="title-icon" title="刷新列表" @click="initTree()">
          <mars-icon icon="refresh" width="14"></mars-icon>
        </p>
        <p v-if="plotTotal > 0">共{{ plotTotal }}条数据</p>
      </a-space>
    </div>
    <mars-tree
      draggable
      block-node
      checkable
      :tree-data="plotTreeData"
      :field-names="{ title: 'name' }"
      v-model:checkedKeys="checkedKeys"
      @drop="onDrop"
      @check="onPlotTreeCheck"
    >
      <template #title="node">
        <mars-dropdown-menu :trigger="['contextmenu']">
          <span @click="flyTo(node)">{{ node.name }}</span>
          <template #overlay>
            <a-menu v-if="node.group && !isAutoGroup">
              <a-menu-item @click="addNewPlotTree(false, node)">重命名分组</a-menu-item>
              <a-menu-item @click="onMenuDeleted(node)">删除分组</a-menu-item>
              <a-menu-item @click="onMenuSaveGeojson(node)">导出JSON</a-menu-item>
              <a-menu-item @click="onMenuSaveKML(node)">导出KML</a-menu-item>
            </a-menu>
            <a-menu v-else-if="!node.group">
              <a-menu-item @click="onClickMarkerEditor(node)">编辑标绘</a-menu-item>
              <a-menu-item @click="onMenuDeleted(node)">删除标绘</a-menu-item>
              <a-menu-item @click="onMenuSaveGeojson(node)">导出JSON</a-menu-item>
              <a-menu-item @click="onMenuSaveKML(node)">导出KML</a-menu-item>
            </a-menu>
          </template>
        </mars-dropdown-menu>
      </template>
    </mars-tree>
  </div>
</template>
<script setup lang="ts">
import { onUnmounted, onMounted, ref, toRaw } from "vue"
import { $message } from "@mars/components/mars-ui"
import type { AntTreeNodeDropEvent } from "ant-design-vue/es/tree"
import * as mapWork from "./map"
import { useWidget } from "@mars/common/store/widget"
import { logInfo } from "@mars/utils/mars-util"
import { Modal } from "ant-design-vue"

const { activate } = useWidget()

interface PlotTreeItem {
  id: string | number
  key: string | number
  name: string
  open: boolean
  group: boolean
  type: string
  children?: PlotTreeItem[]
}

const plotTreeData = ref<PlotTreeItem[]>([])
const checkedKeys = ref<string[]>([])
const plotTotal = ref<number>(0)

let isAutoGroup = false // 是否自定义分组

onMounted(() => {
  initTree()
})

mapWork.eventTarget.on("refreshTree", (event: any) => {
  const { key } = event
  refreshTreeList(key, { ...event })
})

function initTree(autoGroup = true) {
  const showIds = [] // 是显示状态的图层id集合
  const openIds = [] // 展开的树节点id集合（如果不想展开，对应图层配置open:false）

  let index = 1
  let itemTotal = 0

  const result = mapWork.getGraphicsTree({
    autoGroup: autoGroup ? "type" : "",
    forEach: function (item, graphic) {
      item.key = item.id // 树控件api需要的唯一标识
      item.name = item.name || `未命名${index++}` // 树控件api需要的显示文本字段

      if (item.show) {
        showIds.push(item.id)
      }
      if (item.group && item.open !== false) {
        openIds.push(item.id)
      }

      if (!item.group) {
        itemTotal++
      }
    }
  })
  logInfo("获取到的矢量数据树", result)

  if (!result) {
    return
  }

  plotTotal.value = itemTotal
  // 赋予树控件
  plotTreeData.value = result.tree
  checkedKeys.value = showIds
  isAutoGroup = result.isAutoGroup
}

/**
 * 改变树控件列表
 * key - 操作执行
 * nodeId -  被删除的node id | 被修改的node id
 * node - 被添加的对象
 * obj - 被修改的node 属性
 */
function refreshTreeList(key: "remove" | "change" | "add", { nodeId, node, obj }) {
  switch (key) {
    case "remove": {
      loop(plotTreeData.value, nodeId, (item, index, arr) => {
        arr.splice(index, 1)
      })
      break
    }
    case "change": {
      loop(plotTreeData.value, nodeId, (item, index, arr) => {
        arr[index] = { ...item, ...obj }
      })
      break
    }
    case "add":
      plotTreeData.value.unshift(node)
      break

    default:
      break
  }
}
const loop = (data, key: string | number, callback: any) => {
  data.forEach((item, index) => {
    if (item.key === key) {
      return callback(item, index, data)
    }
    if (item.children) {
      return loop(item.children, key, callback)
    }
  })
}
// ************************icon**************************** //
// 添加一个新的图层 || 给分组重新命名
const addNewPlotTree = async (isAdd: boolean, node: any) => {
  if (isAdd && isAutoGroup) {
    Modal.confirm({
      title: "提示",
      content: "手动添加分组，自动分组将失效，是否继续",
      icon: null,
      okType: "default",
      okText: "确定",
      cancelText: "取消",
      class: "mars-global-alert",
      onOk() {
        initTree(false)
        $message("自动分组已取消，清空数据可再次自动分组")

        activate({
          name: "addPlotTree",
          data: {
            isAdd,
            groupId: "",
            inputName: "",
            isAutoGroup
          }
        })
      }
    })
  } else {
    activate({
      name: "addPlotTree",
      data: {
        isAdd,
        groupId: isAdd ? "" : node.id,
        inputName: isAdd ? "" : node.name
      }
    })
  }
}

// ************************树控件**************************** //
// 定位
const flyTo = (node: any) => {
  mapWork.flyToPlotTreeGraphic(node.id)
}

// 隐藏显示图层
const onPlotTreeCheck = (_checkedKeys: any, e: any) => {
  mapWork.showHideGarahic(e.checked, e.node)
}

/*
 * 移动节点至另一个大节点下
 * info.dragNode 被移动的小节点
 * info.dragNodesKeys 被移动的小节点所处大节点的key
 * info.dropPosition 被移动的小节点所处的位置
 * info.node 移动之后被迫更改的节点（上一个节点）
 * info.dropToGap {boolean} 是否拖拽位置在同一个父组件
 *
 **/
const onDrop = (info: AntTreeNodeDropEvent) => {
  if (isAutoGroup) {
    $message("当前为自动分组，无法拖拽；创建分组可取消自动分组")
    return
  }
  const dragNode = info.dragNode
  const dropKey = info.node.key
  const dropPos = info.node.pos!.split("-")
  const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])

  const data = [...toRaw(plotTreeData.value)]

  // console.log("dropKey", dropKey)
  // console.log("dragNode", dragNode)
  // console.log("info", info, info.node)
  // console.log("dropPosition", dropPosition)

  // 文件夹内移动位置，好像sdk本身没有支持
  if (!info.dropToGap && !info.node.group) {
    $message("请移动到文件夹下")
    return
  }

  let dragObj
  let pid = info.node.key

  loop(data, dragNode.key, (item, index: number, arr) => {
    arr.splice(index, 1)
    dragObj = item
  })

  if (!info.dropToGap) {
    // 同一文件夹下
    loop(data, dropKey, (item, _index) => {
      dragObj.pid = pid

      item.children = item.children || []
      item.children.unshift(dragObj)
    })

    mapWork.moveToLayer(String(dragObj.key), String(pid))
  } else if (
    (info.node.children || []).length > 0 && // Has children
    info.node.expanded && // Is expanded
    dropPosition === 1 // On the bottom gap
  ) {
    loop(data, dropKey, (item, index) => {
      item.children = item.children || []
      item.children.splice(index + 2, 0, dragObj)
    })
  } else {
    let ar: any[] = []
    let i = 0
    loop(data, dropKey, (_item: any, index: number, arr: any[]) => {
      ar = arr
      i = index

      pid = arr[index].pid
    })
    if (dropPosition === -1) {
      ar.splice(i, 0, dragObj)
      pid = null
    } else {
      ar.splice(i + 1, 0, dragObj)
    }

    mapWork.moveToLayer(String(dragObj.key), String(pid))
  }

  plotTreeData.value = data
}

// ************************右键菜单**************************** //
// 矢量数据的右键菜单
// 是否编辑
const onClickMarkerEditor = (node: any) => {
  if (!node.checked) {
    Modal.confirm({
      title: "提示",
      content: "当前矢量处于隐藏状态，是否显示并开始编辑",
      icon: null,
      okType: "default",
      okText: "确定",
      cancelText: "取消",
      class: "mars-global-alert",
      onOk() {
        mapWork.openEditorPannel(node.id, true)

        checkedKeys.value.push(node.key)
      }
    })
  } else {
    mapWork.openEditorPannel(node.id)
  }
}

// 删除对应矢量数据
const onMenuDeleted = (node: any) => {
  mapWork.onMenuDeleted(node)
}

// 导出geojson
const onMenuSaveGeojson = (node: any) => {
  mapWork.onMenuSaveGeojson(node, node.name)
}

// 导出KML
const onMenuSaveKML = (node: any) => {
  mapWork.onMenuSaveKML(node, node.name)
}
</script>

<style lang="less" scoped>
.graphic-three {
  // padding: 14px;

  .data-tree-title {
    padding: 7px 10px;
    border-top: 1px solid white;
    border-bottom: 1px solid white;
    color: #eaf2ff;

    .title-icon {
      display: inline-block;
      width: 22px;
      height: 22px;
      padding: 0px 0px 0 3px;
      border: 1px solid white;
    }
  }
}
</style>
